package de.dhbw.karlsruhe.picsim.codeimport;

import de.dhbw.karlsruhe.picsim.model.memory.CommandRegisterAddress;
import de.dhbw.karlsruhe.picsim.model.memory.OpCode;
import de.dhbw.karlsruhe.picsim.model.memory.impl.CommandRegisterAddressImpl;
import de.dhbw.karlsruhe.picsim.model.memory.impl.OpCodeImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Scanner;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 9, 2010
 * Time: 12:22:31 PM
 */
public final class LSTFileImpl implements LSTFile {
    private static final int HEX_RADIX = 16;
    private static final Log log = LogFactory.getLog(LSTFileImpl.class);


    private final Collection<LSTLine> lines = new ArrayList<LSTLine>();

    public LSTFileImpl(@NotNull final Readable reader) {

        final Scanner scanner = new Scanner(reader);

        while (scanner.hasNextLine()) {
            final String line = scanner.nextLine();
            log.debug("line = " + line);


            final String processRegisterNumber = line.substring(0, 4);
            final CommandRegisterAddress registerAddress = createCommandRegisterAddress(processRegisterNumber);

            final String opCodeString = line.substring(5, 9);
            final OpCode opCode = createOpCode(opCodeString);
            lines.add(new LSTLineImpl(opCode, registerAddress, line.substring(9)));
        }
        final IOException ioException = scanner.ioException();
        if (ioException != null) {
            log.error("Exception occurred : ignoring", ioException);
        }
    }

    @Nullable
    private static OpCode createOpCode(final String opCodeString) {
        return isWhiteSpace(opCodeString) ? null : OpCodeImpl.createOpCode(Integer.parseInt(opCodeString, HEX_RADIX));
    }

    @Nullable
    private static CommandRegisterAddress createCommandRegisterAddress(final String argument) {
        return isWhiteSpace(argument)
               ? null
               : CommandRegisterAddressImpl.createUnSafe(
                Integer.parseInt(argument, HEX_RADIX));
    }

    private static boolean isWhiteSpace(final String toCheck) {
        //noinspection DynamicRegexReplaceableByCompiledPattern
        return toCheck.matches("\\s*");
    }

    @Override
    @NotNull
    public Iterable<? extends LSTLine> getLines() {
        return Collections.unmodifiableCollection(lines);
    }
}
